package com.twu.biblioteca;

import java.util.LinkedList;
import java.util.Scanner;

/**
 * This class represents the library. Class provides methods to list books available in the library,
 * check out and return books from and to the library
 */

public class BibliotecaApp {

    private Scanner scanner = new Scanner(System.in);

    /**
     * List of the books of the library
     */
    private LinkedList<LinkedList> list_books;

    /**
     * List of movies in the library
     */
    private LinkedList<LinkedList> list_movies;

    /**
     * List of users registered in the library
     */
    private LinkedList<LinkedList> list_users;

    /**
     * Library number of user logged in
     */
    private String lib_number;

    /**
     * Password of the user logged in
     */
    private String password;


    /**
     * Creates a library with specified list of books, list of movies, and list of users
     * @param list_books list of books owned by the library
     * @param list_movies list of movies owned by the library
     * @param list_users list of users registered in the library
     */
    public BibliotecaApp(LinkedList<LinkedList> list_books, LinkedList<LinkedList> list_movies, LinkedList<LinkedList> list_users){
        this.list_books = list_books;
        this.list_movies = list_movies;
        this.list_users = list_users;
    }

    /**
     * @return welcome message
     */
    public String welcome(){
        return "Welcome to the library!";
    }

    /**
     * Prints welcome message
     */
    public void printWelcome(){
        System.out.println(welcome());
        System.out.println();
    }

    /**
     * Generates menu with options of actions which can be taken in the library
     * @return menu
     */
    public LinkedList getMenu(){
        LinkedList menu = new LinkedList();
        menu.add("Choose from Menu:");
        menu.add("[1] List Books");
        menu.add("[2] Check out book");
        menu.add("[3] Return book");
        menu.add("[4] List Movies");
        menu.add("[5] Check out movie");
        menu.add("[6] My profile info");
        menu.add("[7] Quit");
        return menu;
    }

    /**
     * Switches user to appropriate menu section
     * @param menu_option menu option which user has chosen
     * @return boolean which is used to determine if user stays in the system or quits
     */
    public boolean change(int menu_option){
        if(menu_option == 1){
            listBooks();
            printMenu();
            return true;
        }
        else if (menu_option == 2){
            checkOutBook();
            printMenu();
            return true;

        }
        else if (menu_option == 3){
            returnBook();
            printMenu();
            return true;

        }
        else if(menu_option == 4){
            listMovies();
            printMenu();
            return true;
        }
        else if(menu_option == 5){
            checkOutMovie();
            printMenu();
            return true;
        }
        else if(menu_option == 6){
            printProfileInfo(getUserInfo(lib_number, password));
            printMenu();
            return true;
        }
        else if(menu_option == 7){
            return false;
        }
        else{
            System.out.println("Select a valid option!");
            return true;
        }

    }

    /**
     * Prints out the list of books currently available in the library
     */
    public void listBooks(){
        System.out.println("List of available books:");
        for(int i = 1; i < list_books.size(); i++) {
            if (!list_books.get(i).getLast().equals("Checked out")) {
                System.out.println("-------------------------");
                System.out.println(list_books.get(0).get(0) + ": " + list_books.get(i).get(0));
                System.out.println(list_books.get(0).get(1) + ": " + list_books.get(i).get(1));
                System.out.println(list_books.get(0).get(2) + ": " + list_books.get(i).get(2));
            }
        }
        System.out.println();
    }

    /**
     * Checks if book/movie is available to check out
     * @param itemToCheck title of the book/movie user intended to check out
     * @return true if book/movie is available and false otherwise
     */
    public boolean checkAvailability(String itemToCheck, String category){
        boolean avail = false;
        if(category.equals("book")) {
            for (int i = 1; i < list_books.size(); i++) {
                if (list_books.get(i).get(0).equals(itemToCheck) && !list_books.get(i).getLast().equals("Checked out")) {
                    avail = true;
                    break;
                }
            }
        }
        else if(category.equals("movie")){
            for (int i = 1; i < list_movies.size(); i++) {
                if (list_movies.get(i).get(0).equals(itemToCheck) && !list_movies.get(i).getLast().equals("Checked out")) {
                    avail = true;
                    break;
                }
            }
        }
        return avail;
    }

    /**
     * Marks book/movie as checked out by adding "Checked out" record in the list of books/movies
     */
    public void markAsCheckedOut(String itemToMark, String category){
        if(category.equals("book")) {
            for (int i = 1; i < list_books.size(); i++) {
                if (list_books.get(i).get(0).equals(itemToMark)) {
                    list_books.get(i).addLast("Checked out");
                    break;
                }
            }
        }
        else if(category.equals("movie")){
            for (int i = 1; i < list_movies.size(); i++) {
                if (list_movies.get(i).get(0).equals(itemToMark)) {
                    list_movies.get(i).addLast("Checked out");
                    break;
                }
            }
        }
    }

    /**
     * Calls method to check if book which user wants to check out is available in the library. If it is, calls method to
     * mark that book as checked out.
     */
    public void checkOutBook(){
        System.out.println("Please type the title of the book you would like to check out:");
        String bookToCheck = scanner.nextLine();
        if(checkAvailability(bookToCheck, "book")) {
            markAsCheckedOut(bookToCheck, "book");
            System.out.println("You have successfully checked out the book");
        }
        else
            System.out.println("That book is not available. Try again please.");
        System.out.println();
    }

    /**
     * Prints out the menu of the system
     */
    public void printMenu(){
        LinkedList menu = getMenu();
        for(int i = 0; i < menu.size(); i++)
            System.out.println(menu.get(i));
        System.out.println();
    }


    /**
     * Checks if book is valid to be returned by checking if the book belongs to the library and is currently checked out
     * @param bookToCheck title of the book user intends to return
     * @return true is the book is valid, otherwise - false
     */
    public boolean checkValidity(String bookToCheck) {
        for (int i = 1; i < list_books.size(); i++)
            if (list_books.get(i).get(0).equals(bookToCheck) && list_books.get(i).getLast().equals("Checked out"))
                return true;
        return false;

    }

    /**
     * Marks book as returned by deleting "Checked out" record in the list of books
     * @param bookToReturn title of the book user intends to return
     */
    public void markAsReturned(String bookToReturn){
        for (int i = 1; i < list_books.size(); i++){
            if(list_books.get(i).get(0).equals(bookToReturn)) {
                list_books.get(i).removeLast();
                break;
            }
        }
    }

    /**
     * Calls method to check if the book user intends to return is valid to be returned to the library. If it does, marks
     * book as returned.
     */
    public void returnBook(){
        System.out.println("Please type the title of the book you would like to return:");
        String bookToReturn = scanner.nextLine();
        if(checkValidity(bookToReturn)) {
            markAsReturned(bookToReturn);
            System.out.println("You have successfully returned the book");
        }
        else
            System.out.println("That is not a valid book to return. Try again please.");
        System.out.println();
    }

    /**
     * Prints out the list of movies currently available in the library
     */
    public void listMovies(){
        System.out.println("List of available movies:");
        for(int i = 1; i < list_movies.size(); i++) {
            if (!list_movies.get(i).getLast().equals("Checked out")) {
                System.out.println("-------------------------");
                System.out.println(list_movies.get(0).get(0) + ": " + list_movies.get(i).get(0));
                System.out.println(list_movies.get(0).get(1) + ": " + list_movies.get(i).get(1));
                System.out.println(list_movies.get(0).get(2) + ": " + list_movies.get(i).get(2));
                System.out.println(list_movies.get(0).get(3) + ": " + list_movies.get(i).get(3));
            }
        }
        System.out.println();
    }

    /**
     * Calls method to check if movie which user wants to check out is available in the library. If it is, calls method
     * to mark that movie as checked out.
     */
    public void checkOutMovie(){
        System.out.println("Please type the title of the movie you would like to check out:");
        String movieToCheck = scanner.nextLine();
        if(checkAvailability(movieToCheck, "movie")) {
            markAsCheckedOut(movieToCheck, "movie");
            System.out.println("You have successfully checked out the movie");
        }
        else
            System.out.println("That movie is not available. Try again please.");
        System.out.println();
    }

    /**
     * Checks if user with given library number and password is registered in the library
     * @param lib_number user's library number
     * @param password user's password
     * @return true if such users belongs to the library, otherwise returns false
     */
    public boolean checkIdentity(String lib_number, String password) {
        //   getListOfUsers();
        for (int i = 0; i < list_users.size(); i++)
            if (list_users.get(i).get(0).equals(lib_number) && list_users.get(i).get(1).equals(password))
                return true;
        return false;
    }

    /**
     * Calls method to check if user's identity. If user enters correct library number and password, welcome message and
     * library menu are shown. Scanner reads user's chosen menu option
     */
    public void tryToLogIn(){
        System.out.println("Enter your library number:");
        lib_number = scanner.nextLine();
        System.out.println("Enter your password:");
        password = scanner.nextLine();
        System.out.println();
        if(checkIdentity(lib_number, password)){
            printWelcome();
            printMenu();
            boolean switcher = true;
            while(switcher){
                int menu_option = scanner.nextInt();
                scanner.nextLine();
                switcher = change(menu_option);
            }
        }
        else{
            System.out.println("Library number or password are wrong. Please try again.");
            System.out.println();
            tryToLogIn();
        }
    }

    /**
     * Returns name, email address, phone number of user who is logged in
     * @param lib_number user's library number
     * @param password user's password
     * @return list containing user's name, email address, phone number
     */
    public LinkedList getUserInfo(String lib_number, String password){
        LinkedList user_info = new LinkedList();
        for(int i = 0; i < list_users.size(); i++){
            if(list_users.get(i).get(0).equals(lib_number)&&list_users.get(i).get(1).equals(password)){
                user_info.add(list_users.get(i).get(2));
                user_info.add(list_users.get(i).get(3));
                user_info.add(list_users.get(i).get(4));
            }
        }
        return user_info;
    }

    /**
     * Print's out user's name, email address, phone number
     * @param user_info list containing user's name, email address, phone number
     */
    public void printProfileInfo(LinkedList user_info){
        System.out.println("Your profile info:");
        System.out.println("Name: "+ user_info.get(0));
        System.out.println("Email: "+ user_info.get(1));
        System.out.println("Number: "+ user_info.get(2));
        System.out.println();
    }


}